package com.lancoo.cvas.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.lancoo.cvas.entity.Teacher;
import com.lancoo.cvas.entity.TeachingClassWeek;
import com.lancoo.cvas.pojo.common.HourType;
import com.lancoo.cvas.pojo.constant.GlobalConstant;
import com.lancoo.cvas.pojo.dto.ScheduleDto;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @ClassName ClassHourUtil
 * @Description 处理导出字符串显示格式
 * @Author quin
 * @Date 2023/3/13 16:14
 */
public class ExcelFormatUtil {

    /**
     *  对响应进行预处理
     * @param request
     * @param response
     * @param fileName
     * @return
     */
    public static ServletOutputStream pretreatment(HttpServletRequest request, HttpServletResponse response,
                                                   String fileName) {
        ServletOutputStream os = null;
        try {
            String agent = request.getHeader("USER-AGENT");
            response.setContentType("application/vnd.ms-excel;charset=utf-8");

            if (agent != null && agent.toLowerCase().indexOf("firefox") > 0) {
                fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
                response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            } else {
                fileName = URLEncoder.encode(fileName, "utf-8");
                response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            }
            os = response.getOutputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return os;
    }

    /**
     * 将rows 写入输出流中
     *
     * @param rows 输入内容
     * @param modelString 模板名称
     * @param passLine 跳过表头行数
     * @param out 输出流
     */
    public static void writeRowsToExcel(List<List<Object>> rows, String modelString, int passLine, ServletOutputStream out) {
        //写入到输出流
        String modelPath = GlobalConstant.MODEL_EXCEL_PATH + modelString;
        String storePath = "/" + "temp/" + UUID.randomUUID() + ".xlsx";
        String targetPath = GlobalConstant.OUTPUT_EXCEL_PATH + storePath;
        FileUtil.copy(modelPath, targetPath, true);
        ExcelWriter writer = ExcelUtil.getWriter(targetPath);
        writer.setSheet(0);
        for (int i = 0; i < passLine; i++) {
            writer.passCurrentRow();
        }
        writer.write(rows);
        writer.flush(out, true);
        writer.close();
        FileUtil.del(targetPath);

    }

    /**
     * 设置导出excel单元格格式
     *
     * @param writer
     */
    public static void setFont(ExcelWriter writer) {
        CellStyle cellStyle = writer.createCellStyle();
        Font font = writer.createFont();
        //红色字体
//        font.setColor(HSSFColor.HSSFColorPredefined.DARK_RED.getIndex());
        //字体加粗
        font.setBold(true);
        cellStyle.setFont(font);
        //垂直居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //水平居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);

        writer.setRowStyleIfHasData(0, cellStyle);
        writer.setRowStyleIfHasData(1, cellStyle);
        writer.setRowStyleIfHasData(2, cellStyle);

        writer.setColumnWidth(-1, 20);
        writer.setDefaultRowHeight(20);
    }

    /**
     * 获取周学时字符串
     *
     * @param classWeeks
     * @return
     */
    public static String getWeekHourString(List<TeachingClassWeek> classWeeks) {
        Map<Integer, TeachingClassWeek> weekMap = new HashMap<>();
        if (CollUtil.isNotEmpty(classWeeks)) {
            weekMap = classWeeks.stream().collect(Collectors.toMap(TeachingClassWeek::getHourType, Function.identity()));
        }
        //周学时
        String lectureWeek = ObjUtil.isNull(weekMap.get(HourType.LECTURE.getCode())) ? Integer.toString(0)
                : weekMap.get(HourType.LECTURE.getCode()).getWeekNum() + "(" + GlobalConstant.roomTypeMap.get(weekMap.get(HourType.LECTURE.getCode()).getRoomType()) + ")";
        String experimentalWeek = ObjUtil.isNull(weekMap.get(HourType.EXPERIMENTAL.getCode())) ? Integer.toString(0)
                : weekMap.get(HourType.EXPERIMENTAL.getCode()).getWeekNum() + "(" + GlobalConstant.roomTypeMap.get(weekMap.get(HourType.EXPERIMENTAL.getCode()).getRoomType()) + ")";
        String computerWeek = ObjUtil.isNull(weekMap.get(HourType.COUMPUTER.getCode())) ? Integer.toString(0)
                : weekMap.get(HourType.COUMPUTER.getCode()).getWeekNum() + "(" + GlobalConstant.roomTypeMap.get(weekMap.get(HourType.COUMPUTER.getCode()).getRoomType()) + ")";
        String otherWeek = ObjUtil.isNull(weekMap.get(HourType.OTHER.getCode())) ? Integer.toString(0)
                : weekMap.get(HourType.OTHER.getCode()).getWeekNum() + "(" + GlobalConstant.roomTypeMap.get(weekMap.get(HourType.OTHER.getCode()).getRoomType()) + ")";
        String weekDistribution = StrUtil.join("-", Arrays.asList(lectureWeek, experimentalWeek, computerWeek, otherWeek));
        return weekDistribution;
    }

    /**
     * 获取周次字符串  1-18:讲授、19-23:上机
     *
     * @param classWeeks
     * @return
     */
    public static String getWeekString(List<TeachingClassWeek> classWeeks) {
        StringBuilder weeks = new StringBuilder();
        if (CollUtil.isNotEmpty(classWeeks)) {
            classWeeks.stream().sorted(Comparator.comparing(TeachingClassWeek::getHourType)).collect(Collectors.toList())
                    .forEach(a -> {
//                        weeks.append(WeekUtil.binaryToString(a.getWeek()));
//                        if (a.getHourType() == 0) {
//                            weeks.append("、");
//                        }else {
//                            weeks.append(":").append(GlobalConstant.hourTypeMap.get(a.getHourType())).append("、");
//                        }
                        weeks.append(WeekUtil.binaryToString(a.getWeek())).append(":")
                                .append(GlobalConstant.hourTypeMap.get(a.getHourType())).append("、");
                    });
            if (StrUtil.isNotBlank(weeks)) {
                weeks.deleteCharAt(weeks.lastIndexOf("、"));
            }
        }
        return weeks.toString();
    }

    /**
     * 获取前端显示教师名称
     *
     * @param teachers
     * @return
     */
    public static String getTeacherName(List<Teacher> teachers) {
        List<String> teacherNameList = new ArrayList<>();
        if (CollUtil.isNotEmpty(teachers)) {
            teacherNameList = teachers.stream()
                    .map(o -> o.getTeacherName() + "(" + o.getBaseTeacherId() + ")")
                    .collect(Collectors.toList());
        }
        String teacherName = StrUtil.join(",", teacherNameList);
        return teacherName;
    }

    /**
     * 获取前端显示教师工号
     * @param teachers
     * @return
     */
    public static String getTeacherNo(List<Teacher> teachers) {
        List<String> teacherNameList = new ArrayList<>();
        if (CollUtil.isNotEmpty(teachers)) {
            teacherNameList = teachers.stream().map(Teacher::getBaseTeacherId).collect(Collectors.toList());
        }
        String teacherName = StrUtil.join(",", teacherNameList);
        return teacherName;
    }

    /**
     * 场地节次处理  讲授：二[1、2节]惟义楼1303
     *
     * @param schedules
     * @return
     */
    public static String getSiteSection(List<ScheduleDto> schedules) {
        Map<Integer, List<ScheduleDto>> scheduleMap = new HashMap<>();
        StringJoiner siteSectionString = new StringJoiner("\n");
        if (CollUtil.isNotEmpty(schedules)) {
            scheduleMap = schedules.stream().collect(Collectors.groupingBy(ScheduleDto::getHourType));
        }
        //讲授 0103  三位
        scheduleMap.forEach((hourType, scheduleList) -> {
            StringJoiner hourTypeToSection = new StringJoiner("-");
            Map<String, List<ScheduleDto>> scheduleMapByTimeCode = scheduleList.stream().filter(scheduleDto -> StrUtil.isNotBlank(scheduleDto.getTimeCode())).collect(Collectors.groupingBy(scheduleDto -> scheduleDto.getTimeCode().substring(0, 2)));
            scheduleMapByTimeCode.forEach((key, value) -> {
                //key 为第几周 value为该周课表
                Map<String, List<ScheduleDto>> scheduleMapByRoom = value.stream().collect(Collectors.groupingBy(scheduleDto -> scheduleDto.getBuildingName() + scheduleDto.getRoomName()));
                scheduleMapByRoom.forEach((room,scheduleByRoom)->{
                    String weekSection = "{}:{}[{}节] {}";
                    String week = TimeCodeUtil.DAY_NAME.get(TimeCodeUtil.DAY_CODE.indexOf(key));
                    List<Integer> sectionList = value.stream().map(a -> Integer.valueOf(a.getTimeCode().substring(2))).distinct().sorted().collect(Collectors.toList());
                    hourTypeToSection.add(StrUtil.format(weekSection, HourType.getByCode(hourType).getMsg(), week, StrUtil.join("、", sectionList), room));

                });
            });
            siteSectionString.add(hourTypeToSection.toString());
        });
        return siteSectionString.toString();
    }

    /**
     * 获取连续、单周连续或双周连续
     * [[1, 3], [4, 5, 6], [8]]
     *
     * @param list
     * @return
     */
    public static List<List<Integer>> getContinuousNumber(List<Integer> list) {
        List<List<Integer>> listList = new ArrayList<>(list.size());
        int max = list.get(0);
        int count = 0;
        for (int i = 0; i < list.size(); i++) {
            if (i == 0) {
                listList.add(CollUtil.newArrayList(list.get(i)));
            } else {
                int plus;
                boolean b;
                if (listList.get(count).size() >= 2) {
                    plus = listList.get(count).get(1) - listList.get(count).get(0);
                    b = ((list.get(i) != max + plus)) ? (list.get(i) != max + plus) ? true : false : false;
                } else {
                    b = ((list.get(i) != max + 1)) ? (list.get(i) != max + 2) ? true : false : false;
                }
                if (b) {
                    count++;
                    listList.add(CollUtil.newArrayList(list.get(i)));
                } else {
                    listList.get(count).add(list.get(i));
                }
            }
            max = list.get(i);
        }
        return listList;
    }

    /**
     * 获取周数  3-6周
     *
     * @param reorganizeWeek
     * @return
     */
    public static String getWeekStringByList(List<Integer> reorganizeWeek) {
        String string = "";
        if (reorganizeWeek.size() > 1) {
            string += reorganizeWeek.get(0).toString() + "-" + reorganizeWeek.get(reorganizeWeek.size() - 1).toString();
            if (reorganizeWeek.get(1) - reorganizeWeek.get(0) == 1) {
                string += "周";
            } else {
                if (reorganizeWeek.get(0) % 2 == 0) {
                    string += "双周";
                } else {
                    string += "单周";
                }
            }
        } else {
            string += reorganizeWeek.get(0).toString() + "-" + reorganizeWeek.get(0).toString() + "周";
        }
        return string;
    }

    /**
     * @param periods 最大节次
     * @param week    0:小周 7  1:大周 14
     * @return
     */
    public static List<List<String>> getScheduleFormat(int periods, int week) {
        List<List<String>> rows = new ArrayList<>();
        List<String> heads = new ArrayList<>();
        for (int i = 1; i <= periods; i++) {
            heads.add("第" + i + "节");
        }
        List<String> weekList = CollUtil.newArrayList("节数\\星期", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"
                , "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日");
        ;
        List<String> headList = new ArrayList<>();
        for (int i = 0; i <= week; i++) {
            headList.add(weekList.get(i));
        }
        rows.add(headList);
        for (int i = 0; i < periods; i++) {
            List<String> tmpRows = new ArrayList<>();
            for (int j = 0; j <= week; j++) {
                if (j == 0) {
                    tmpRows.add(heads.get(i));
                } else {
                    tmpRows.add("--");
                }
            }
            rows.add(tmpRows);
        }
        return rows;
    }

    /**
     * 获取二进制周次
     *
     * @param numbers 易读周次 1/2/3/4/5/7/8/9/10/11/12/13/14/15/16/17/18
     * @param maxWeek 总周次 20
     * @return 11111111111111111100
     */
    public static String toBinary(String numbers, int maxWeek) {
        String[] numberArray = numbers.split("/");
        StringBuilder binaryBuilder = new StringBuilder();
        for (int week = 1; week <= maxWeek; week++) {
            if (Arrays.asList(numberArray).contains(Integer.toString(week))) {
                binaryBuilder.append("1");
            } else {
                binaryBuilder.append("0");
            }
        }
        return binaryBuilder.toString();
    }

    /**
     * 获取易读周次
     *
     * @param binaryString 二进制周次 11111111111111111100
     * @return 易读周次 1/2/3/4/5/7/8/9/10/11/12/13/14/15/16/17/18
     */
    public static String fromBinary(String binaryString) {
        StringBuilder resultBuilder = new StringBuilder();
        if (StrUtil.isBlank(binaryString)) {
            return resultBuilder.toString();
        }
        char[] binaryArray = binaryString.toCharArray();
        for (int week = 0; week < binaryArray.length; week++) {
            if (binaryArray[week] == '1') {
                // 加 1 是因为周数从 1 开始
                resultBuilder.append(week + 1);
                resultBuilder.append("/");
            }
        }
        // 删除最后一个多余的 "/"
        if (resultBuilder.length() > 0) {
            resultBuilder.deleteCharAt(resultBuilder.length() - 1);
        }
        return resultBuilder.toString();
    }


    public static void main(String[] args) {
        UUID sss宋 = UUID.randomUUID();
        System.out.println(sss宋);
        System.out.println(sss宋.toString().length());

    }
}
